import concurrent.futures
import multiprocessing
import time
import numpy as np
from .TraMeasure import MeasureAlgorithm
from tqdm import tqdm
import json


class ParallelMeasure:
    def __init__(self, trajectoryList=[], needLcss=False, theta=45):
        self.trajectoryList = trajectoryList
        self.needLcss = needLcss
        self.theta = theta

    # 根据行列索引，给出计算结果
    def calculateValue(self, row, col, isLcss):
        return (
            MeasureAlgorithm.LCSS(
                self.trajectoryList[row], self.trajectoryList[col], self.theta
            )
            if isLcss
            else MeasureAlgorithm.Hausdorff(
                self.trajectoryList[row], self.trajectoryList[col]
            )
        )

    # 将结果转为矩阵
    def changeToMatrix(self, itemList):
        spatialMatrix = None
        directionMatrix = None
        spatialList = None
        directionList = None
        len2 = int((len(self.trajectoryList) ** 2 - len(self.trajectoryList)) / 2)
        if self.needLcss:
            # 将空间位置度量和空间方向度量的结果区分
            spatialList = itemList[:len2]
            directionList = itemList[len2:]
            # 构建空间方向度量矩阵
            directionMatrix = np.zeros(
                (len(self.trajectoryList), len(self.trajectoryList))
            )
            directionMatrix[np.tril_indices(len(self.trajectoryList), k=-1)] = np.array(
                directionList
            )

            # 沿对角线对称
            directionMatrix[
                (
                    np.tril_indices(len(self.trajectoryList), k=-1)[1],
                    np.tril_indices(len(self.trajectoryList), k=-1)[0],
                )
            ] = directionMatrix[np.tril_indices(len(self.trajectoryList), k=-1)]
            # 归一化
            directionMatrix = (directionMatrix - np.min(directionMatrix)) / (
                np.max(directionMatrix) - np.min(directionMatrix)
            )

        else:
            spatialList = itemList
        # 构建空间位置度量矩阵
        spatialMatrix = np.zeros((len(self.trajectoryList), len(self.trajectoryList)))
        spatialMatrix[np.tril_indices(len(self.trajectoryList), k=-1)] = np.array(
            spatialList
        )
        # 沿对角线对称
        spatialMatrix[
            (
                np.tril_indices(len(self.trajectoryList), k=-1)[1],
                np.tril_indices(len(self.trajectoryList), k=-1)[0],
            )
        ] = spatialMatrix[np.tril_indices(len(self.trajectoryList), k=-1)]
        # 归一化
        spatialMatrix = (spatialMatrix - np.min(spatialMatrix)) / (
            np.max(spatialMatrix) - np.min(spatialMatrix)
        )
        return spatialMatrix, directionMatrix

    def simulate_time_consuming_computation(self, index):
        len2 = (len(self.trajectoryList) ** 2 - len(self.trajectoryList)) / 2
        # 获得对应索引值
        rowIndexs, colIndexs = np.tril_indices(len(self.trajectoryList), k=-1)
        # 空间度量
        if index < len2:
            # 解析出元素所在行列
            row = rowIndexs[index]
            col = colIndexs[index]
            return self.calculateValue(row, col, False)
        # 方向度量
        else:
            # 解析出元素所在行列
            row = rowIndexs[int(index - len2)]
            col = colIndexs[int(index - len2)]

            return self.calculateValue(row, col, True)

    def run(self):
        # 列表长度
        listLen = (
            len(self.trajectoryList) ** 2 - len(self.trajectoryList)
            if self.needLcss
            else (len(self.trajectoryList) ** 2 - len(self.trajectoryList)) / 2
        )
        itemList = []
        start_time = time.time()
        with concurrent.futures.ProcessPoolExecutor(
            max_workers=multiprocessing.cpu_count()
        ) as executor:
            # 使用 map 函数将列表并行处理
            results = tqdm(
                executor.map(
                    self.simulate_time_consuming_computation,
                    [i for i in range(int(listLen))],
                ),
                total=listLen,
            )
            itemList.extend(results)
        # 结果转为矩阵
        spatialMatrix, directionMatrix = self.changeToMatrix(itemList)
        end_time = time.time()
        print("Total execution time:", end_time - start_time, "seconds")
        return spatialMatrix, directionMatrix


if __name__ == "__main__":
    trajectoryList = [
        # [[0, 0], [1, 0], [2, 0]],
        # [[0, 1], [1, 1], [2, 1]],
        # [[0, 2], [1, 2], [2, 2]],
        # [[0, 2], [1, 2], [2, 2]],
        # [[0, 2], [1, 2], [2, 2]],
        [[0, 0], [1, 0], [2, 0]],
        [[0, 1], [1, 1], [2, 1]],
        [[0, 2], [1, 2], [2, 2]],
        [[0, 3], [1, 3], [2, 3]],
        [[0, 4], [1, 4], [2, 4]],
        [[0, 5], [1, 5], [2, 5]],
        [[0, 6], [1, 6], [2, 6]],
        [[0, 7], [1, 7], [2, 7]],
        [[0, 8], [1, 8], [2, 8]],
        [[0, 9], [1, 9], [2, 9]],
        [[0, 10], [1, 10], [2, 10]],
        [[0, 11], [1, 11], [2, 11]],
    ]
    # trajectory_json = None
    # with open(
    #     "./data/compressRouteMatchTaxiGps_厦门T4_曾厝垵(修复特征+人为纠正+属性赋值).json",
    #     "r",
    #     encoding="utf-8",
    # ) as json_file:
    #     trajectory_json = json.load(json_file)
    # trajectoryList = list(
    #     map(
    #         lambda feature: feature["geometry"]["coordinates"],
    #         trajectory_json["features"],
    #     )
    # )
    # 创建对象
    parallelMeasure = ParallelMeasure(trajectoryList)
    # 执行
    spatialMatrix, directionMatrix = parallelMeasure.run()
    print(spatialMatrix, directionMatrix)
